package net.guerlab.smart.platform.user.service.service.impl;

import net.guerlab.commons.number.NumberHelper;
import net.guerlab.smart.platform.commons.Constants;
import net.guerlab.smart.platform.commons.util.OrderEntityUtils;
import net.guerlab.smart.platform.server.service.BaseServiceImpl;
import net.guerlab.smart.platform.user.core.domain.MenuDTO;
import net.guerlab.smart.platform.user.core.exception.MenuKeyInvalidException;
import net.guerlab.smart.platform.user.core.exception.MenuKeyLengthErrorException;
import net.guerlab.smart.platform.user.core.exception.MenuKeyRepeatException;
import net.guerlab.smart.platform.user.core.exception.MenuPathInvalidException;
import net.guerlab.smart.platform.user.core.searchparams.MenuPermissionSearchParams;
import net.guerlab.smart.platform.user.core.searchparams.MenuSearchParams;
import net.guerlab.smart.platform.user.service.entity.Menu;
import net.guerlab.smart.platform.user.service.mapper.MenuMapper;
import net.guerlab.smart.platform.user.service.service.MenuPermissionService;
import net.guerlab.smart.platform.user.service.service.MenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Optional;

/**
 * 菜单服务实现
 *
 * @author guer
 */
@Service
public class MenuServiceImpl extends BaseServiceImpl<Menu, Long, MenuMapper> implements MenuService {

    private MenuPermissionService menuPermissionService;

    private Menu selectByKey(String menuKey) {
        MenuSearchParams searchParams = new MenuSearchParams();
        searchParams.setMenuKey(menuKey);
        return selectOne(searchParams);
    }

    @Override
    protected void insertBefore(Menu entity) {
        String menuKey = StringUtils.trimToNull(entity.getMenuKey());
        String path = StringUtils.trimToNull(entity.getPath());
        String componentPath = StringUtils.trimToNull(entity.getComponentPath());

        if (menuKey == null) {
            throw new MenuKeyInvalidException();
        }
        if (menuKey.length() > MENU_KEY_MAX_LENGTH) {
            throw new MenuKeyLengthErrorException();
        }
        if (selectByKey(menuKey) != null) {
            throw new MenuKeyRepeatException();
        }
        if (path == null) {
            throw new MenuPathInvalidException();
        }

        entity.setMenuId(sequence.nextId());
        if (!NumberHelper.greaterZero(entity.getParentId())) {
            entity.setParentId(Constants.DEFAULT_PARENT_ID);
        }
        entity.setMenuKey(menuKey);
        entity.setDisplayName(StringUtils.trimToEmpty(entity.getDisplayName()));
        entity.setDomain(StringUtils.trimToEmpty(entity.getDomain()));
        entity.setModule(StringUtils.trimToEmpty(entity.getModule()));
        entity.setPath(path);
        entity.setActiveKey(StringUtils.trimToEmpty(entity.getActiveKey()));
        entity.setComponentPath(Optional.ofNullable(componentPath).orElse(MenuDTO.DEFAULT_COMPONENT_PATH));
        entity.setIcon(StringUtils.trimToEmpty(entity.getIcon()));
        entity.setIconCls(StringUtils.trimToEmpty(entity.getIconCls()));
        if (entity.getHidden() == null) {
            entity.setHidden(false);
        }
        if (entity.getLeaf() == null) {
            entity.setLeaf(false);
        }
        if (entity.getRedirect() == null) {
            entity.setRedirect(false);
        }
        OrderEntityUtils.propertiesCheck(entity);
    }

    @Override
    protected void updateBefore(Menu entity) {
        entity.setDisplayName(StringUtils.trimToNull(entity.getDisplayName()));
        entity.setDomain(StringUtils.trim(entity.getDomain()));
        entity.setModule(StringUtils.trim(entity.getModule()));
        entity.setPath(StringUtils.trimToNull(entity.getPath()));
        entity.setActiveKey(StringUtils.trim(entity.getActiveKey()));
        entity.setComponentPath(StringUtils.trimToNull(entity.getComponentPath()));
        entity.setIcon(StringUtils.trim(entity.getIcon()));
        entity.setIconCls(StringUtils.trim(entity.getIconCls()));

        String menuKey = StringUtils.trimToNull(entity.getMenuKey());

        if (menuKey != null) {
            Menu other = selectByKey(menuKey);
            if (other != null && !Objects.equals(other.getMenuId(), entity.getMenuId())) {
                throw new MenuKeyRepeatException();
            }
        }
        entity.setMenuKey(menuKey);
    }

    @Override
    protected void deleteByIdAfter(Long menuId, Boolean force) {
        clearMenuPermission(menuId);
    }

    private void clearMenuPermission(Long menuId) {
        if (!NumberHelper.greaterZero(menuId)) {
            return;
        }

        MenuPermissionSearchParams searchParams = new MenuPermissionSearchParams();
        searchParams.setMenuId(menuId);

        menuPermissionService.delete(searchParams);
    }

    @Autowired
    public void setMenuPermissionService(MenuPermissionService menuPermissionService) {
        this.menuPermissionService = menuPermissionService;
    }
}
